{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#all_slow"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Tutorial - Migrating from Lightning\n",
    "\n",
    "> Incrementally adding fastai goodness to your Lightning training"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We're going to use the MNIST training code from Lightning's 'Quick Start' (as at August 2020), converted to a module. See `migrating_lightning.py` for the Lightning code we are importing here."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from migrating_lightning import *\n",
    "\n",
    "from fastai.vision.all import *"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Using fastai's training loop"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can use the Lightning module directly:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model = LitModel()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To use it in fastai, we first pull the DataLoaders from the module into a `DataLoaders` object:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data = DataLoaders(model.train_dataloader(), model.val_dataloader()).cuda()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can now create a `Learner` and fit:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: left;\">\n",
       "      <th>epoch</th>\n",
       "      <th>train_loss</th>\n",
       "      <th>valid_loss</th>\n",
       "      <th>accuracy</th>\n",
       "      <th>time</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>0</td>\n",
       "      <td>0.367197</td>\n",
       "      <td>0.333293</td>\n",
       "      <td>0.910800</td>\n",
       "      <td>00:11</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "learn = Learner(data, model, loss_func=F.cross_entropy, opt_func=Adam, metrics=accuracy)\n",
    "learn.fit_one_cycle(1, 0.001)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As you can see, migrating from Lightning allowed us to reduce the amount of code, and doesn't require you to change any of your existing data pipelines, optimizers, loss functions, models, etc. Once you've made this change, you can then benefit from fastai's rich set of callbacks, transforms, visualizations, and so forth.\n",
    "\n",
    "For instance, in the Lightning example, Tensorboard support was defined a special-case \"logger\". In fastai, Tensorboard is just another `Callback` that you can add, with the parameter `cbs=Tensorboard`, when you create your `Learner`. The callbacks all work together, so you can add an remove any schedulers, loggers, visualizers, and so forth. You don't have to learn about special types of functionality for each - they are all just plain callbacks.\n",
    "\n",
    "Note that fastai is very different from Lightning, in that it is much more than just a training loop (although we're only using the training loop in this example) - it is a complete framework including GPU-accelerated transformations, end-to-end inference, integrated applications for vision, text, tabular, and collaborative filtering, and so forth. You can use any part of the framework on its own, or combine them together, as described in the [fastai paper](https://arxiv.org/abs/2002.04688)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Taking advantage of fastai Data Blocks"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "One problem in the Lightning example is that it doesn't actually use a validation set - it's just using the training set a second time as a validation set.\n",
    "\n",
    "You might prefer to use fastai's Data Block API, which makes it really easy to create, visualize, and test your input data processing. Here's how you can create input data for MNIST, for instance:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mnist = DataBlock(blocks=(ImageBlock(cls=PILImageBW), CategoryBlock), \n",
    "                  get_items=get_image_files, \n",
    "                  splitter=GrandparentSplitter(),\n",
    "                  get_y=parent_label)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here, we're telling `DataBlock` that we have a B&W image input, and a category output, our input items are file names of images, the images are labeled based on the name of the parent folder, and they are split by training vs validation based on the grandparent folder name. It's important to actually look at your data, so fastai also makes it easy to visualize your inputs and outputs, for instance:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAOsAAAD3CAYAAAD8HqM1AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nOy9WXCc15mY/Xy97ysaWwONlSAWLqJESqJl0dYynokcR448U7FTE3suXKlkqqbyp3KT69zlLjVTFf+ZuCqL/0lmkrHHGnk0ZdnWWBItkeJOgiQ2Amg0Gmg0utH7vnz/Bf0dNUhwkwh0N/A9VSiJ6O30wXnPec+7SrIso6Ki0vpomj0AFRWVx0MVVhWVNkEVVhWVNkEVVhWVNkEVVhWVNkEVVhWVNkEVVhWVNqElhVWSpP9PkqR1SZLSkiTNSZL0/WaPqR2QJCl7z09NkqQ/a/a42oVWX3dSKwZFSJI0BSzIslySJGkc+DXwdVmWLzV3ZO2DJElWYAN4Q5blD5s9nnag1dddS56ssizflGW5pPzztz8jTRxSO/L7QBT4qNkDaRdafd21pLACSJL0nyVJygMzwDrwbpOH1G58D/ifciuqTi1MK6+7llSDFSRJ0gKnga8C/1GW5UpzR9QeSJIUAJaAUVmWl5o9nnajVdddy56sALIs12RZPgv0Af+62eNpI74LnFUF9fPRquuupYW1AR0tdHdoA74L/I9mD2If0FLrruWEVZKkTkmSvi1Jkk2SJK0kSb8LfAd4v9ljawckSfoS4Af+b7PH0k60w7pruTurJEk+4K+B49zdTILAn8qy/F+bOrA2QZKk/wJYZFn+F80eSzvRDuuu5YRVRUVlZ1pODVZRUdkZVVhVVNoEVVhVVNoEVVhVVNoE3SMeP+jWJ+kLvFadu8+POnc7oJ6sKiptgiqsKiptgiqsKiptgiqsKiptgiqsKiptgiqsKiptgiqsKiptwqP8rCoq+xpZlpFlmWq1SrlcFv8GkKS77k6tVotGo0Gj0aDT3RUZjWbvzzlVWFUONNVqlWq1ysLCAn/xF39BJpNha2uLWq2G0+nEYrEwODjIkSNH6OjoYGRkBL1ej8FgQKvV7ulYW0pYG9P1Gne4J0XZEZux+6m0F7VajUqlQiQS4de//jUbGxusra1RrVbp7OzEbrfz/PPPI8syIyMj9PT0YLFY0Ov1ez7WpgqrLMuUSiXq9boQzFKpRCqVIpVK8cknn5BMJpEkSQjgo3C73QwMDOD1epmcnMRkMj3R61UOBsphkEwmWV1d5dq1a6ytrZFOp6nVasiyTCaToVQqcenSJaLRKP39/SSTSfr6+jh16hQOh2NPx9x0YS2Xy+KuUKvVSCaTLC0tMTs7y3/6T/+JYDD4RMI2NDTEl7/8ZQ4fPszw8DBGo1EVVJUdkWWZra0trl+/zuLiIrFYjGKxKB7P5/Pk83mSySSzs7P09PRQKpUYHBxkampqfwurcj+oVquk02lKpRKhUIhkMkm9XqdWqxGNRgkGg0SjUbLZ7BN/RjabZWlpCY1Gw8zMDN3d3XR2dmI2m9FoNKrgqiDLslhvyWSSlZUVKpUKU1NTVCoVJEmiWq2yurpKKpUSrzMajXR3d9Pd3S0MTXvJnn5ipVIhm80Sj8f5+OOPiUajnD9/nmAwKNSSdDpNLBajVqtRKpWeWIWNx+N8+umnLC0tYbFY6Ovr41vf+haBQACtVtuUSVZpPZRDY3l5mWvXruF0OnnttdfQarVIkkSpVOLdd9/dJqxOp5Px8XGhse01e7pyy+UysViMjY0NlpeXicfjrK6uEovFqNfrABQKBQqFgvi3IqiPK7CyLFOpVMjn82xsbCBJEtlslmq1eiBPVeX+Va/XhW2gUqlQr9cpFovU63V0Oh06nQ6DwYDFYjkQd3xJktBoNHR1dTE8PIzL5cLv91Or1UgkEmQymfuMSAaDAafTidVqbcr87KmwhkIh/uqv/oq1tTU++OADcrkc2WxWLChg2/9/ETKZDO+//z5ut5vTp0/T0dGBy+VCr9fv+4WoIMsyhUKBYrFIPp8nm82STCa5du0aW1tbXLlyhXA4zMjICF1dXbz88st87WtfQ6/Xo9Pp9u08SZIkvuPp06c5ceKE8KVmMhl+9atfUSqV7vMm2Gw2BgcH6erq2v9qcLFYJBaLEY1G2djYoFAobHtc2e1MJhPAfc5phcaTotGS3EitViOVSgnVulwuU6vVdumbPX2U77STC+vek6/xOcp/lbnJZrPiJ5FIEIlEmJ+fF1eRSCTC5uYmo6Oj9PX1UalU0Gg0Qh3cryhzaLFYsFgs981f46GhrEuz2YzFYsFkMu3/oAin08nU1BR6vZ6PP/54m7CaTCZMJhP9/f0cP34cnU73QGHN5/OsrKyQzWZZXl7+XIaoVqZer4vNJZVKkcvlxGMGgwG73Y5Wq0Wv16PRaEin06RSKWq1GsVikUKhwNzcHKlUisXFReLxOOVymWKxSDabJRKJUCgUxH0sGo2Sz+cZGhpidXUVl8tFZ2fngfJTVyoVCoUCGxsbnD9/nrm5OSKRCAAdHR309vYyMjKCw+EQxsq9Zk+F1Ww209/fTzwe36ZGSJIk7kuBQIAjR45gMBiAuwv33olJJBJoNBqSySTr6+uPJaztdEo0hr/FYjHi8bh4TDkFDAYDVqtVzEM4HKZQKJBMJonFYpw/f55oNMr09DTRaPSBnyVJErlcjlwuRyQSIRaLodFo6Ojo2Iuv2jLUajWy2SxbW1ssLi4yMzNDJpMBwGq1EggE8Hq9mM1msUnuNU05WTs7OzGZTNtODLPZjMFgwO/3Mz4+ft9kNApbPp/nxIkTbGxskE6nuXHjBqVSiXK5LJ5jNBrp6+uju7ubkZERXC5X2/hcy+UyN2/eJBqNcu3aNbHDw93v5Xa7hbBqtVohZJVKhVKpJE7WdDq9bY4fRGdnJx0dHYyNjREIBMTJfRAol8tUKhXW1tb4h3/4B1ZWVlhaWiKXywkN45VXXuHVV19laGgIi8XStCvCngqrzWbDYrHQ39/P5OTktruYcofQ6/WPFKp6vU6lUiGVSvHpp58KX22jsJrNZo4fP05vby/9/f04HI62UetKpRJ///d/z+zsLOfPn2d1dVU8JkmSMP4oweXlcplqtQpw393rUcY6SZIIBAJMTExw/Phxenp6MBgMbTNXXwQlgi6VSnH58mV+8IMfEI/H2djYQJZlBgYGCAQCvPbaa3zjG994rLW5m+y5SUsxXhgMhh2FVVmAD0OJfMrn85RKJSqVyn3GI61WK+7ByuJuh1NVQafTCcu1LMtYrVZsNhtwdw5rtZoIh6tWq8LV1YgkSbhcLkwmk4iBVdxajfaA3t5eDh06hN/v3/eGJbi72RcKBXGihsNhZmZmSCQSlEolHA4HBoOBY8eOMTIywuDgIHq9vunaxp4Ka2PKkVarvU9YH5dyuUwoFCISiYhIp0ple79brVaL0+nE6/U2JUPii6DRaPB4PHi9XrFwBgcHOXr0KJIkCUPSb37zGzY3Nx/4PlqtlqmpKQYGBsR9bGtri4WFBaGFaDQajh49yltvvYXH4zkQwlqtVpmfn2d1dZV/+Id/4Ny5c2xsbLC+vo7ZbGZqaore3l6++93vcvToUSwWiwiCaObcNCWc50kDHRSUELFyuUwikRBWzJ1OFr1ej8vlwuv1NiVD4oug0Wjwer2k02lGRkaoVqscPnyYwcFB4O5iKxQKjIyMYLFYHvg+RqOR4eFh/H4/0WiUUqlELpfbNu8ajUac2krSw35HlmWy2SzRaJRoNEooFCKXy1GtVtFoNCJE1ePxYLPZWsbn3Faxd9lslvX1dTY2NnjvvffY2NggFAqJRIBGvF4vX//61xkcHMTlcjVpxJ8Pk8nE7/zO71AsFvnmN79JoVDAZrNht9sBtsW1Ngae34tGoxFq8IcffsiPf/zjbRuXTqfDaDTicDjECX4QqNfrhEIhZmdnCQaDxGIxqtUqsizjcrl47bXXmJiYoK+vr6Xu7y0trPcGBighhMvLy6ysrLC5uUk+n7/vVFWc3V1dXbjd7rY7WRUV3uFw4PV6kWVZ+FXhs/nw+XyPNCApkTl+v3+bPUAxVGm1WoxGIzqdrmUW5V6QzWbJZDJkMpltG57JZCIQCNDT04PJZGqp61PLCmulUiGRSFAoFFhcXCQUChEMBlleXiadTnPr1i3hH2zEYrHg9Xrp7+9vmj/si6IY2mRZFgamxu+hqGR6vf6hwlqv14nFYqTTac6dO8e1a9fIZDJUq1X0ej2Dg4N0d3cTCATECdIK6t5uI0kSHo8Hn89HR0cHFotFJI5ks1kuXrzI1tYWBoNBeChaQetoWWGt1Wqsra2xubnJT37yEy5evMjm5iabm5tUq9UHhg5aLBb8fj8ej6dl7hqfh0dZryVJeuSuX61WiUaj3Lp1i1u3brG4uCi0EKPRyNDQEH6/vy21jy+K0+nE7XbjdDoxm80Ui0Vxp5+dnSWVSjE6OorNZsNqtR48Ya3VatRqNarVqrDg5nK5+yy5cDcQ/+OPP2Zzc5M7d+4Qi8WEEaDxNFHS3gYGBhgYGBBBEMPDwwcmg+RhlEolEonEfXdbvV5Pf3+/CKE7SGi1WgYGBrBardRqNex2O8FgkAsXLgCIENYPPviAcDjM4cOHGRoaQqfTNdUIt+fJ58riUUpl3Lx5k0Qicd9zM5kMFy5cEGU2lMDqe909RqMRs9nMK6+8wle/+lX6+/sZGhrCZDKJaJODilKaRIn0asRkMnHkyBFOnjyJ2+1u0gibg16vZ3h4mMHBQQKBgMgCu3PnDplMhqtXrwJw8eJFLBYL3/72t/nOd76Dy+VqWuI57JGwKoKWy+WIRqNsbm4yPz9PIpFgfX19W+yrQiqVIp1Oi2D/nXYzxe1gtVrp7OwkEAjg8XiwWCwHzmDSiBLhVS6XhfU8kUiIO7Ber8dsNtPR0SFCFw8aiuHNarXi9XoZGBhgamqKSCTCwsKCSHool8usra2xuLhIf38/HR0dwqaw1yfsrgurklNZKpU4e/Ysf/mXf0k8HufOnTsijnWn+6dy4X8Yer2esbEx/H4/Z86c4dixY6K2qzKhB5FKpcLKygrxeJxf/vKX/PznPxdRS0ajEY/Hw8DAAEeOHGFgYODAVs+QJEmEwFosFjweD3Nzc/z5n/85wWCQYrFIOp3mF7/4BXNzc5w+fZp/82/+DS6XC7PZvOfztiefpqR8ra+vc/36dVKplDAUPYpGi+i9KGqwkrGjxG0e5Dsq3J3vZDJJJBJhY2NjW5STVqvFbrfjdru3ReYcVBSBs9ls9Pf3A+D3+0mlUiQSCZGmODs7S39/P7lcDpPJtP/LujTyONUgGv2nOwlgqVTixo0bLC8v88ILL9DX14fNZsPhcBxogS2Xy5w9e5b5+XmWlpa2PebxeHjppZcYGBh4aPTTQcNoNArL+L/7d/+O9fV1fvOb3zA/P08wGBRBFD/72c8YHBzkq1/9Ki6X67Fi2Z8WLa3/POhEVVCqIW5tbYkgCUmSsNvtB1pYK5UKi4uL3Lx5k2Qyue0xJWd4cHDwQN5VH4RerxdZNSdOnODQoUNks1nq9Tq5XI6FhQWi0Sg3btwgmUxy6tSpPV9neyKsisP9xRdfpFgsEo/HmZubo1ar4fP5HlomVFGDATY3NwmFQsJA1ZgSp3J/3xalgDqA3W7H6XRy7NgxvvKVr9DV1SXK56h8hkajwWg0otFoOH78OHa7nUqlwvXr16lWq9y8eZN0Os2VK1dEKZy9CmfddWGVJEksivHxcQYGBtja2uLcuXPU63WOHj2K0+l8LOvtwsICZ8+eZWlpScQEA3uqirQySqF0JdlBqV4Id4MAxsbGmJiY4MSJEwferfUglFpLRqORw4cP09vby/r6OjabjUKhwLVr11hcXKSnp4eFhQXefPPN/SOsjSh5rA6Hg9HRUWRZxuv1YrFYHssU3tnZydTUFNVqta2jk3YLxWVTKBTI5XKk02kRcKLT6bbVD1I3t4ejRIgZjUZhUKpUKqJYn1Ixci+L8O2psCqB4yaTCafTCbBNSB8lfCaTCb/fj9fr5b/9t/+2YzDFQaZarZJKpYhGoywuLhIOh8VicjgcdHR04PV6hY9R5eEoIZgulwuXy0W9XheF6bLZLKlU6pHuxafJniefNyagPylK0rp6qu5MpVIRBdOU0EwFJR3uINVN/qI0ttlQCqMrKL9/GjWuH5eWtgbfSz6fZ319fVulA5XP3GCRSIQf/vCHrK2t3VfR0Gg0YrVaVXfNY6KkZKZSKVZWVlhbW9tmA2gGuyqsD6r7+3nfRykSHo/H26pg916gFDO/ceMG4XB4W+C+UurVZDKp7pp7eNDJqBRTy2QypNNp0TlCoRmF0J+6sCpfXsmsqVar2O12kVv6eUq5JJNJMpkMly5d4he/+AVra2uPVWLzoKCU09zc3CQYDBKPx0U3NJvNhtFo5Pjx43zjG9/A6/Ue2PBCBcVqXq/XSSQSolayEqqq1GY+d+4ct27dYmZmZptQm0wmjh07xjPPPIPP59uzce/KX03x9Sn9LpW+Io0+0yd5r1gsRjAY5IMPPuD//J//Q6lU2tOLfatTrVZFksTGxoYoTq1UzLDb7Rw6dIiJiQlx7z/oKC6ucDjMpUuXhOHTYrHQ29uLLMt88sknXLp0ieXl5W3CajQamZyc3PMerU9NWJXdPZ/PE4/HSaVSXLlyhUqlwhtvvCFKgj5OmVHl8q4kBE9PT3Pt2jWCwaBoK6FMnqKOKD8HzXii3K2U4l+NdyqtVsuhQ4cYGhpiaGhItQL/FuVkVRIeLl68KO70RqOR1dVVZFkmGAwSDofJZDLIsozD4WB4eJiRkRH8fj8Oh2NPtZSn8knKgtna2mJ+fp533nmHWCzGxx9/jCRJDA0N0dnZefcDH/HlFF9hqVRiaWmJeDzO3/zN3/D++++Tz+e39cdpLLmhhIsdxMUYj8e5cuUKy8vL2+5Ver2eU6dO8aUvfYmxsTHVEvxblLaXuVyOTz75hB/96EfY7XY6OztFgrksy2L9KQdDV1cX3/jGNxgaGhJtItvyzprNZkXeXyQSIRKJkE6n0Wg0RKNRkskkJpPpkZk25XJZ1FZaWFgQmSO5XE5YgLVareg54vP5cDgcdHd3i8iTg7IglRMik8kQDodJJpPiqqGodR0dHfj9ftUK3IBSijSRSJBOpykWi2g0GlKp1Laa1kqfYI1Gg8FgED1claqHe53h9dRO1hs3bvAXf/EXrK2tcePGDaESGwwGLly4QLlcxmw2Y7VaH/pea2trok/LjRs3RKpSYxV5u90ueuZ86UtfIhAI8Oyzz9LT03Ngin4pp0O1WuX69ev83d/9HZFIhEqlglarxev10tnZyYsvvsjRo0dV33QD1WqVK1eucOPGDWZnZ4G7noaNjQ0AoZ0p0V82mw2Xy8XExARnzpwRDar2Wot7aidrIpFgaWmJjY0NUqmUuDvJskw8HicYDGI0Gh958q2trXHr1i0SiQTz8/MUCoVtrTV0Oh02m43e3l58Pp9o++ByuQ6cW6KxfnA4HCabzYqypWazGafTid1ux2w2N3uoLYVysqZSKXGtUvrZNqKsOaWsrdIhoVlx1bt+O65UKqLfpUajeWQVvUwmQyKRoFwuC7XXYrFgMBjo7+9ndHSU4eFh3nrrLdEeQ4nfPEjU63XRzTwajRKPx0UxOYvFwsmTJ+nt7RXWSvVU/QydTsczzzxDT08P4XCY8+fP3/ccSZJELPU//sf/mG9+85v09vaKSpBt3/JxpwVRr9cJh8OEw+Eneq/GgAqlEkRfXx+jo6McP36cI0eOYDQaD6QFGO7OT7FYJJfLkclk7mu43NXVhd/vPzAtMZ4EjUaDz+fDZDLh9Xp3fI4kSUI7OXz4MM8//7wI6G+WEfOpCevk5CRvvfUWoVCIy5cvk0gkWFxcfGh7h0aUFvCKccRgMNDd3Y3NZmN8fJzOzk4GBwc5dOiQcOwfRMvv42A2mzl8+DDj4+OPtBEcRBRB1Gq1DA4OMjU1xdbWFhsbG6IJmNvt5tSpU/T39/PlL3+5qX1ZFZ6KsEqSxPDwMB6Ph+XlZSwWC2tra2xsbDy2sNrtdtFESmkYPDk5idfr5dVXX6Wvrw+Hw4HValXrLD0Cu93O8ePHGRwcVO+rO9CYszoxMcHJkydZXFxkc3MTi8XCc889R09PD9/61rcYHR3FbDZjNpubvuaemrDq9XpsNhudnZ0cO3aMjo4OYrEY4XCYtbU1kVpUr9eFGVyv14uK6IovVimTqfzO5XLh8/mwWq0H1o/6IJR2D/cmNSibmbqpPRhlbnp7ezl16hSBQID+/n7MZjPHjh3D5/Ph8/la6qr11NRgJUhcqRKXy+U4fPgwwWCQv/u7v+P8+fMUi0UKhQIul4uXXnoJp9PJ5OQkHR0doiemwWAQ9wJFMBWVtxUmrFWo1+tsbW0RCoVEeKHKk6HRaBgfH2d0dHSbNVhxc7XauntqwqrcNZXwP4Cenh7RAEnxlebzeXp7ewkEArhcLoaHh/F6vfh8PpxOp7ivtsoEtSqNUTiPU9JVZWeUyLd24Km7bhTflMlkYmxsjJGRESYmJigUCiLuV1F1lSgbxaWjhMOpgvpoZFkmmUzu2BpDZX+yK35W5ZRVLJEHrfHRXqHEUNfr9W2lcZQ7lrrp7S8OdmJjG6PVahkfH8fj8ZBIJIhEIrjdbvr6+hgcHKSnpwe73a6mw+0jVGFtU7RaLd3d3bhcLsbHx7lz5w49PT2i3KvH42m5zt0qXwxVWNsUxV0GcOLECeBua4ze3l6cTueB6mR+UJAeUZ1t70q3tSZfZKXv+twpf7tGt0Nj0kOTBbWl567F2XHuWi7CwGazbfvRarX8yZ/8SbOH1ZIogqnVatHr9bjdblwul8i2UefuyfjDP/xDenp6cDgcjI2N8cMf/rDZQ9rGo07WpiJJkhXYAN6QZfnDZo+nnVDn7smRJGkKWJBluSRJ0jjwa+Drsixfau7I7tJyJ+s9/D4QBT5q9kDaEHXunhBZlm/KsqxU4pN/+zPSxCFto9WF9XvA/5Rb+fhvXdS5+xxIkvSfJUnKAzPAOvBuk4ckaFk1WJKkALAEjMqyvPSo56t8hjp3XwxJkrTAaeCrwH+UZbnS3BHdpZVP1u8CZ9XF9rlQ5+4LIMtyTZbls0Af8K+bPR6FVhfW/9HsQbQp6tw9HXSod9aHI0nSlwA/8H+bPZZ2Q527z4ckSZ2SJH1bkiSbJElaSZJ+F/gO8H6zx6bQqhFM3wN+Isuymqj55Khz9/mQuavy/r/cPcSCwP8jy/LbTR1VAy1rYFJRUdlOS6rBKioq96MKq4pKm6AKq4pKm6AKq4pKm/Aoa/BBtz6paV6fH3XuPj/tkSKnoqKyM6qwqqi0Caqwqqi0Caqwqqi0Caqwqqi0Caqwqqi0Caqwqqi0Ca2adaOi0hSUhl9KaVfYXuq18fdwt7GV0m1ut8u/qsKqotJAqVTi5s2bJJNJ0ft2Y2ODSCRCNptlY2ODWq2GTqdDp9Pxj/7RP+LUqVM4nU7cbve2VqVPG1VYVVQaqFarhMNhVlZWSCaTFItFwuEwd+7cIRaLsbCwQLVaRa/XYzQa6e7uZnBwEI1GIxqw7VZTMFVYVVQa0Gg0uN1ucrkcc3NzLC0tEYlEWFtbEx374K46XCqV+Oijj9jc3GRqaorXX38dl8slmoI/bVRhVVFpQKPRYLfbcblcxONxrly5Qi6X29YDV5IkcY/99NNP+fTTTzlz5gxOp5ORkRE6OzsPtrDKskytVqNWq1GtVrfdJ/L5PHa7HbPZjMPhwOPxiAbNamMmlSdBo9Hg8/kwm8187WtfY3h4mHw+Tz6fJ5PJsLCwQCaTIRQKkc/nRb+hjY0Nrl27RqFQ4Nlnn8VkMj11dbgtGlPJsowsy5RKJQqFAolEgsuXL7O6usqPf/xj5ufnOXbsGMPDw5w6dYo33ngDq9UqeuV8AdTMkc9P285dvV7fZhWu1WpUKhU2Njb42c9+Rjgc5p133mFlZUWsTaPRiN1u5/Tp0/zpn/4p3d3dwkr8Odhx7lruZFW+vCzLlMtl6vU6lUqFSqVCJpMhkUiwtbXF3Nwcm5ubrK2tsbW1RTgcxmQysby8TCgUasv+pIpqVa/XxXd/ktcpi+phKI2stFqtmB+9Xt9W87TbKAImSZLQ6HQ6HU6nk8HBQSRJwm63o9PpqFaryLJMtVoVp2+pVKJarT51y3DLCWu9XqdarVIqlZiZmSGRSDA9PU0kEiEcDnP79m1KpRLZbJZKpUIymaRWq7G8vMz6+jq3b9/m6tWrTExM8O///b8XqnA7qMOVSkXcj86fP088Hn/ka2RZJh6Pk0qliMfjwlr5oO9rs9no7u7G7Xbz5ptv4vf76enpwel0Pu2v0/ZoNBpkWUaj0aDT6fB4PJw5c4bNzU3OnTvHysoKxWJRGJ7K5TLpdJpIJILJZKKjowOd7umJWNOEVVG/a7UasiyLxVWr1SiXy2SzWdbW1giHw8zNzbG2tsbc3BwLCwvspLoXi0WKxSKVSoVyuYzNZnvkKdNq1Ot18vk86XSaxcVFotHoI18jyzKxWIx4PM7Kygqzs7PUajWAHQXWYrHQ29uL3+/nyJEjolVko9tB5TMa50Oj0WA0GjEajeh0um2PKRoLILScp105tCnC2qjazs3NEY/HMZvNGAwGUqkUCwsLxGIxLl26xObmJpubm+RyOTKZzCMnoFQqsbW1xdbW1mOrka1CoVBgbm6OxcVFPvzwQ4LB4GO/TrnP1+t1oUlIkiQ6oCvzXS6XiUajZDIZ/uqv/orOzk6+//3vc/r0abRaLQaDQRXYe6hWq1SrVaLRKD/96U8JhUJcu3aNfD5PtVoFwOl0EggEOHr0KAMDA7tiEW6KsCr3gGKxyPT0NPPz87hcLhwOB6urq9y+fZtYLMbFixfJZrNP9N61Wo18Pk8ul2s7YS0WiywvL7O8vMyNGzdYX18Xm9OTCFBj53OdToderwfuLrparUYmkyGTyZBKpTCZTJw5c4bnnntuV9wN+wHlcInFYnz44YcsLCywvr5OuVwWzzGZTAQCAdwcqowAACAASURBVLq6unC5XFgslqc+jqYIa6lUIhQKEYvFuHDhAgsLC1itVgwGA8lkklAoJO6kjej1esxms3DL1Ot10ul026m7D8Jut3Pq1CmGhoaoVCpsbW09UFir1SqRSIRcLkd3d7e4cypXCsUS6fF4sFqtTE9Pc/bsWQqFAltbW2g0Grq7u/F6vXR2dqLX63ctTK5dqVar1Ot1VldXuXz5MrOzs8zNzRGLxbYJKkBfXx8vvvgihw4dEpvj02bPhVWWZYrFIpcvX2ZxcZFf/epXzM3N3fecxv8qmM1m3G43er0em80mDFH7RVgtFgtjY2MMDg7S2dlJLpd74HOLxSIXL15ka2uLqakpRkY+65+kCKtWq6WzsxOLxcIvf/lLotEokUiEdDqNVqtlaGgIv9+/TVhVFfguioW3Uqlw5coV/uzP/oxoNMry8vJ9ggowMDDAa6+9RkdHx/4Q1mKxSD6fZ21tjdu3b7O2tkY6nd5RXZUkCaPRiFarpaOjA7vdzsDAAL29vcBnxphYLEYulxOCrdy7rFZr250UipFCr9fjcrkwm80PfG61WuXYsWMkk0kCgQAdHR3b3kdxG5hMJmGRzOVyFItF6vU6ZrOZyclJRkZG8Pl8bWMx301kWRYqb61WIxqNkkwmmZmZYXNzk3Q6vc14J0kSvb29dHZ2Mjo6KrSYfRHIH41G+eSTT7h9+zY/+tGPSCQSDzw9tFotbrcbm83G7/7u7zIyMsKJEyc4dOgQpVKJjY0N1tbWWFxcZGNjQ7xOMZn7fL628x0qJ5tWq6Wrq+uhz5VlmYGBAeFaeNACURz8pVKJ1dVVstks9Xodp9PJP//n/5wjR47saN08aDQK6vr6OqlUirfffpvp6WlmZ2dZWloSEXTw2aHwO7/zO7z66qscPnwYv98vfNi7wa4Lq6JO1Go1EokEy8vLhMNhEonEtnhLBWUSzGYz/f39eL1e+vv7GRkZEZf3fD7P5ubmjp9lNBrp6urC6XSKxd9Oi1AZ69PwzzWGaJZKJXFlkGUZrVaLzWbDYrG03Rw9TRoDSsrlMsVikY2NDTY3N1ldXWVhYYF4PC5UX8Xn6vV6sdvt9PX1MTAwgNvtFoK6W3O5q8KqLBYlquj999/n7bffJp1OP/BE7ejo4MiRI/T19fHmm2/S3d2N3+/H4XCg1+sxGAzE43HeffddVlZWWF1dFRFPACMjI7z11luMjY1hNpsP7CKEu/OfTqdJJpMEg0EymYwQVkAYoQ7iHClzoLgE19fX+eSTT4jFYly5ckVobul0WgiqVqvFarXi9Xr5l//yXzI5Ocn4+LgILXyaARA7sevCWq/XiUaj3Lx5k/n5eeG038lfKkmScNoHAgEmJyfp6OjAarViNBqFUFYqFYLBIIuLi+Tz+W3v4fF4GB0dxe/37/rktQPFYpFUKiUEVfELwu7lXbYajWut0XipGDtTqRTBYJArV64QjUY5e/bsjlqfTqfDYrHg8/k4fvw4ExMTeL1erFbrnnyPXVnNSlxvKBRia2uLn/3sZ1y9epX5+fkHCqrH48HhcPDSSy/x1ltv0d3dTWdn5zYDSaFQIJVKsby8zMzMDCsrKxQKBeCuU9pisTA8PMzU1BROp7Pt7qy7zUHsxSvLMrlcjng8TrVaJZfLCdeh4ibc2NggHo9z69YtstksxWJx23sYjUbMZjMTExP8/u//Pv39/UxNTeF2u/fUN71rR0+5XGZ6epqFhQXef/99Lly48MDnSpKEw+FgaGiIiYkJXnjhBSwWC1ardZvAFQoFwuEwMzMzLC0tbQvHs1qtdHV10dvbS09Pj7Akq+zMQRBc5TtmMhnu3LlDOp1mdXWVVCrFhQsXCAaDrK2tEYvFHvo+BoMBu93O+Pg43/rWt4Slfq81t6f+aY2q6vT0NHNzcw+McdXpdPj9flwuF6dPn2ZiYoJjx45hsVi25aIqFs3NzU0++ugjFhYWtu1+kiThdDoZGBjA6/UKH+NBUPEeRqOap2ggZrOZzs5OxsbG9nXEkhIwk8lkmJ2d5YMPPiCfz4tSLcFgkK2tLUql0iPfSzE+KdcIZT3uNbumBudyOX71q19x7ty5BwYtmEwmvvzlLxMIBHjrrbeYmpoS0UnwmWVUsWheu3aNH/zgB2QymW0GKkmS6OvrEwEFSsW5g44sy+LakEqlAMTGODAw8FA/brtTr9eZnZ3l4sWLfPLJJ/zsZz8TggaI1LbHCUmtVqsUCgURg10ul5syd7u2opVdvVwu37cL6fV6UdFhYGCA0dFRof8rRg/F5VOv18nlcuTzecLhMOl0mnw+LyZZiX3t7u5mZGQEr9d74E/URkql0jaLpsFgwOv1PvX0rVakUqmIbKwHxYpbrVYsFgvlclk8597nKWmb2WyWaDSKRqPBZrNtyxbbC3btryVJkkhqvteo5PP5eP311+nr6+MP//AP6enpwWQybXPs12o1IaQffvgh169f5/LlyyQSCfF+Wq0Wj8eDzWbjtdde480338RgMKh31d8iyzIbGxssLi4SiUSQZRmv18vJkycZGhrCZDI1e4hNQ4nyOnr0KJOTk6yvr3Pp0iWKxaIIHFFQDo3bt2/zv//3/yYQCPC9732Pzs7OXS09ei+7KqwOhwOHw0GhUKBcLovoHKfTSV9fH4FAQDiX792hGsu4BINBFhYWWF1dFeqL8hlWq5WOjg66u7vF+6gn62c5ldlsllQqRT6fR5IkTCYTPp8Ph8Ox7zc1JfHDarXidDqp1+vbqkDodDr6+/vp7+9HkiQR4aXVaqlWq5TLZSGoSnhrKBRCo9FQLBb3/N761IVV2bGcTiff+973ePnll7lw4QK3b9+mq6uL7u5uxsbG+Pa3vy2EeScBq9VqrK2tEYlEuHHjBufOnSOdTm+bIKvVyte+9jVGRkYYGhpqu1jg3aJarZJMJkmn01y9epXz589TKBRwOBz09vYyMDCw79VgjUbD+Pg4fr+fkydP8vrrr4tQ1MZNyuPxYLfbhVuwUChw584dkskk58+fZ3p6mq2tLTY3N8lkMly5coVMJkM6nRYVOdr6ZFWSnk+cOMHAwABbW1uk02n6+/sZGBjgmWeeYXBw8KFqWK1WE9UPgsEgoVDovucYjUZGRkY4efIkTqdTPVF/S61WI51OixpVoVAIk8mE2WzGZrPhdDqfRjG5lkYpuu1wOHC73fT19WEymbDb7dtO10YbiRIfMDQ0RCqVYmtri0QiQalUIhaLUSqViEQiGAwGisUitVptT+dw17ZWJVvGZrPxzW9+kxdeeEEkmHs8ngfu6qVSiVwuRywW44MPPiAYDLK6urrtOV1dXbz88st0d3fzpS99ib6+Pmw22259lbZDsQLH43FyuRzVahWbzSaSo+91je1XFCFUDJparfaBd8zGmGy3243JZOLEiRMiC0qpZAh3DVehUAifz7drNYJ3YteEVakG53Q66ezsFL9XJuVBC6VUKrG8vMydO3f4+7//e+bn5+8LKVRcPYODg0xOTmKz2fb9wnsSarUaW1tbIgCgVqtht9sZGRmhr69PlNA5CCha3uN8X+Uea7fbsVqtPPPMM/h8PpLJJL/85S/F8yqVCnfu3MFut2OxWLDb7bv5FQS7eml5lGA2olzis9ksd+7c4c6dO6RSqW0lOV0uFx0dHYyNjYl7VztVL9xtFFWuWq0SDAYJBoPk83kMBgN+v5/R0VECgUDbz1WjW08JVDAYDE+tsLby+gd1hlMyyDY2NnZMRN8tWsbCoBT0Wlpa4q//+q8Jh8NEIhERYSJJEkePHuUrX/kKR48eVfMwd0BZxOl0mo8++ohr164Rj8ex2WwcO3aMf/pP/ylut7vtDUuNvve1tTVWVlYYHR3l8OHDe5JJVC6XWV5eplqt8swzzzAwMLBrn9VI0/9q92Y/rK2tsb6+TjQaFelcjSVKBgYG6OnpQa/XH4h715Og5K3mcjmSySRbW1vCvaVcSZT81XZHyT2NxWIsLS3hdrtFAM4XrdDYaGzK5XI7np6KJriX7pumCqsSQ1yr1fjlL3/Jj3/8Y1ZXV5menhaxmErvESVM7s0338RkMqklM3cgmUxy4cIFZmdnmZmZIZlMMj4+Tn9/P5OTk6J6Rru7uOr1OqlUis3NTX71q1/x7rvvsrS0hNlsxuv1EggEMBqNn+u9lRzsSqXC7OwsZ8+eZWFhYVuQhE6nw+fz4ff79yw9DlpAWJUg6du3b/Pzn/+cUqm0zaCk1WpxOBx0dXURCARE0ymV+ykWi8zOzhIMBkkmkxQKBdERzePxiBrC7U7jqbe+vs7MzAz9/f2EQiERJ/55QwGVNVmtVkUC+r1ZORqNBrPZjNPp3NMrRdPqBisRIpcuXWJ+fp4rV66Qz+e31bhxOp3Y7XbeeustnnvuOY4fP66epg+hVCqxvr7O5uam0EoUP+N+Dy2cnZ3lb/7mbwgEAtjtdrxeLw6HA6PR+FhGJ0X1zefzXL58mVAoxIcffsjly5e3lYTVaDRYLBampqZ49tlncblce/H1gCZW5FeKcb/33ntcvHhR9LARA9PpcDgc9PT08Oqrr3Ly5Ekx8So7oxSijsfj1Go1JEkSbTD3+7UhHA7z9ttvc/jwYU6dOsXIyAhGo1G4bB5HWBXD1bvvvsv8/DwXLlwgHA6L5yiuHbPZzKFDhx4Z2PO0aYqwKlUkotEoKysroqi3gmIUefbZZ+np6cHr9aoB+g9BMXTkcjkRsVSpVERgyvDw8J75AvcCJevF5/OJCiNKi4utrS1+85vfsLi4yAsvvEBXVxdut1sU0Gv0HiiGTaXRmVIkbXFxkaWlJZGGqZzMTqeT0dFRRkZGxLViX0QwPQgluuanP/0pKysrfPTRR6yurooLvBLs7/F4+MpXvsLY2JgIFdvPJ8MXQUnhUvoDJZNJABwOB4ODgxw7dgyPx9PkUT49NBoNXq8Xi8VCf38/3d3dwuAUDof58z//c0wmE6+99hoDAwO88sorvPDCC0K4GsMLE4kEKysrTE9Pi0LoV69e3ZZ5o+RY9/X18Xu/93sMDg7S09Oz5wX59lRYld0vk8mIIP1CobCtiJfFYhGngRIet99VuC+K0pkglUqJBsBKnq/D4cBut++riCVlQzcajfT19XHixAlWVlZEyxWlm2A4HEav1zM7O0t3dzdmsxmXyyVaOcqyTDAYFHWBV1dXRfUIxXYC4Ha76enpYXx8nJGREQKBQFPchnsqrNlslnA4zNWrV3nvvfeIRCL3NZ4aHh7mjTfeYGRkhNOnT4sSpCo7I8syW1tbhEIh5ubmRBNfq9WKw+FgdHSUnp6efVXmRunWoNfref3113nmmWc4e/YsP/jBD4jH40SjUcrlMtevX2dmZoZLly7xzjvvbBNWuKuRhEIhwuEwhUKBTCYjfNXK50iSxJkzZ/gn/+SfMDAwwLFjxzAYDJ/bNfRF2FNhLZfLbG1tiSLKirqmqCVwN6QwEAgwNDSEzWbb91bMp0G5XCaZTIo2IoprweFwYLFY9tWpqqCEAtpsNvR6vQil1Ov1ZLNZJEmiUCiISKdoNIrBYMDhcGwT1lgsJtahglKsW4mQ6+7u5tChQ/h8Pmw2W9MiwPb0U1OpFBcvXmRhYWHHDnF6vZ6RkRFeffVVXC6XeqI+JpVKhUQiQaFQQJZlbDYbZ86cwe/343a7mz28XUW5hx4/fpz/8B/+A7FYjL/9279lfX2dc+fOsbq6KiLhisUihUJhm4Hp3oJpZrOZsbExUVEjEAjw7LPPcvjw4aZ32ttTYc3lcoRCITY3N7fdU+Guq8ZgMODxeOjt7RW7msqjqVar5PN5EW5nNBrp7+9ncHBwXxdFg89OQY/Hg8fjIZPJiLYXc3NzwniphAzeWxP4XoxGI4FAgM7OTl5++WXGxsbo6OhoiXzpPel1k8lkyOfz3Lhxg2vXrhGJRO47WXU6nUiQVmKBVR6NYtFUSr42hsU1e3E1A71ez/PPP8/o6ChWq5VTp04RCoWYmZmhXC6Tz+fRarX09/dvc2d5vV7R5/a5556jo6ODwcFB3G53y/j3d11YlfYZq6urfPrpp3z00Uc7VuU3GAxYLBZRgV89VR+faDTKzMwMy8vL1Ov1A50yaDQaOXToELVaDb/fL9phSJJEOp1mbW0Nk8nE888/vy3PenBwkOeee06Uvmn0QLTKXO6JRFSr1W1lSe8VVEmSGBoaEk2BW2VyWh0l6kaJp1ZUPcVaarFY9kUs8JOgbFRKlzxZljl27Bj5fJ5isUg6nUan0zE+Pr7N99zd3Y3H48FsNrdsssOeCKviA9yphjDcvXd87Wtf45/9s392X0ErlZ1pDDhXKhgqBialGbPP5zuQGoriR3W5XDidTnp6ejh9+vS2g+JeV5Yi4HtZAO1J2ZO/pNFoFCUwzGazaP+uVEG0Wq309vaKjnHqyfp4KDmVyskqyzImkwmbzSbqXR1EYYXPhA+eTq/bVmDXv4VGo6Gvrw+v10sqlWJubo54PE44HMZms/FHf/RHTExMcOLECTwez75y3u8mSpqY0vw3GAzi8Xh47rnnmJyc5MyZM3R1dal+6n3ErgurUljaYDDQ19eH3+/HZDKRTqdFn0slMVoNK3wylJjgQqFAPp/H6/XS29tLV1cXXq9Xrfi4z9gT/UCpiTM+Ps4f//EfUy6XSafTmEwmxsfHReyqKqhPhlarxWAw0NXVxdjYGM8++yyvvvoqQ0NDIhxOndP9w54JK9ztcePz+fbiI/c9yp1MKTEyNjbG4cOHOX36NHa7Xa1PtQ/ZHzfvA4pGo8FgMHDs2DHK5bLoxmc2m1vWoqny+ZEeUZ1t/7fHfjhf5Gja9blT/naKVVhxO7RIUERLz12Ls+Pctdz2a7PZtv1otVr+5E/+pNnDakkaAwCUBtLf/e536e3txeFwMDY2xg9/+MNmD7NtUNqPturcPepkbSqSJFmBDeANWZY/bPZ42gFJkqaABVmWS5IkjQO/Br4uy/Kl5o6s9Wn1uWu5k/Uefh+IAh81eyDtgizLN2VZVvK+5N/+jDRxSG1Dq89dqwvr94D/Kbfy8d+CSJL0nyVJygMzwDrwbpOH1Da08ty1rBosSVIAWAJGZVleavZ42g1JkrTAaeCrwH+UZbny8FeoKLTq3LXyyfpd4KwqqJ8PWZZrsiyfBfqAf93s8bQTrTp3rS6s/6PZg9gH6Gihe1eb0VJz15LCKknSlwA/8H+bPZZ2QpKkTkmSvi1Jkk2SJK0kSb8LfAd4v9lja3XaYe5a8s4qSdJ/ASyyLP+LZo+lnZAkyQf8NXCcuxtxEPhTWZb/a1MH1ga0w9y1pLCqqKjcT0uqwSoqKvejCquKSpugCquKSpugCquKSpvwqHzWg259UtO8Pj/q3H1+2iNFTkVFZWdUYVVRaRNUYVVRaRNUYVVRaRNUYVVRaRNUYVVRaRNUYVVRaRNUYVVRaRNUYVVRaRPUivz7gAc1qG7870HnQamgyu8f9Pi989jM+VSFtc2RZZnFxUWmp6dFg2Wn08no6ChWqxW73X7g2z7m83lSqZToCwxgsVjQarWsrq4SCoVIJpOsr68LodVoNHg8Hmw2G0NDQ/T392OxWLDb7U1r9q0Ka5sjyzLT09P86Ec/olqtUq1W6e7u5g/+4A/o7u5meHhYFdZ8nlAoRKlUIpFIoNFo6Orqwmg08v777/PJJ5+wvLzMtWvXqFaraDQatFotIyMjdHd3c+bMGX7v934Pn8+H1WpVhVXl8+N0Ounq6iKRSHDnzh2q1Spnz57F5/NRKBTo7u4WXeeVznOSJIn/7icU7aJWqxGNRonH46ysrHDr1i1KpRLZbBZJkvB4POj1em7cuMHy8jKxWAxZlsV8yLJMKpUCYHZ2Fr1ej9frZWJiAqPRKNqV+P1+nE4nGo1m1zusq42pHk7LZ47U63Vu3LjBhx9+yK1bt/jpT39KpVJBr9djMpl49dVXGRwcZHJykomJCcxmM263G61Wi9ls3s0F1pS5q9VqFItFisUi//2//3c+/PBDVlZWCIVCovk0IFpilkolyuWyaO4lBv/bPkKSJGEwGDAajeh0OjFn3d3duFwuvv/97/PVr34Vg8GA2Wx+Wpvfjm/SlierYlCRZVlMtLLpVKtV8vm8+Hfj5Dkcjn3XDVySJOx2O0NDQ6RSKQYHB0mn02QyGWq1GvF4fFvjKpvNhtfrxWg04nQ6xSLUarVoNBrxo9Pp2rZtZK1WEypvKBQiHo+TyWS2GeJKpbtdMpS1s9Ohpfy+VCpRqVTQarUUCgV0Oh31ep1sNsvS0hLj4+N4PB5MJtOuaiptK6yVSoVyuczt27eJRqNiQmdmZvjggw8oFAri+TqdDr1ezx//8R/zrW99q20X4U5IkkRfXx9dXV1MTk4yMDBAJBLhN7/5DZFIhBs3blAoFDAYDOKEsNlsWCwWBgcHsdvtDAwMEAgEcLvd+Hw+bDYbvb29bdmNvlarkU6nSSQSrKysMD8/T7VapVar3fe8x0VRrRtP5mKxyObmJu+88w7z8/O8/vrrfOMb39jVtdUUYZVlWagcO7kc7v3CioqivK5er1Mul8nn86yurhIMBimXy5TLZWZnZ/n4448pl8vi9VqtFq1Wy9e//nXRx7TdFuHDUATR4/EwOjqKxWJhYWEBSZJIp9Ok02kKhcK2OTEYDCQSCdxut9j4PB6PmNuurq4dtZN2oFarUalUxPeCz9aAYhy6V+1t/PfD3DzKY+VyGUmSWF1dxWAwsLGx8cDXPS2aIqylUolwOEy5XKZUKm2bNI/HQ2dnJxqNRgjnysoKkUiE+fl5ZmZmxB9DeZ9kMimMCvF4XOx+jciyTCKRIB6PY7FYsFqt++qEhbvuiMnJSUZHRzl69KjY/ROJBGtra4RCIdbW1vj5z39OPp8nGAwSDocJhUI4HA4sFgs2m41Dhw7xb//tv8Xn8wk1uV2QJEloD4FAgGeeeYZKpUK9Xqezs5MjR44gSZJw1yik02k2NjYolUqkUinxmkdRqVTIZDLCJbSbNOWvUC6XCYfDpFIpstnsth3/0KFDuFwuIUjVapWFhQWuXr3KpUuXeO+994QwKsK8045272kgyzK5XI50Og3cXdj7DeWEBfD5fMiyTD6fp1Qqic3u2rVrvP/++1SrVRKJBLIsE41Gt71PJBLhj/7oj3A6nej1+mZ8lc+NJEno9XqMRiNer5dAIEC1WqVUKtHf388LL7yAVqvFYDAQj8fF61KpFLVajWw2Sz6ff+hdVkFRj8vl8v4QVlmWSafT5HI5YrEYq6urRCIRrl+/Tj6fp1wub7s/XLt2jeHhYaGuVKtVpqenWVtbY2FhgUqlsi3q5FGqhyRJdHR04HA46Ovrw+1277ohoFVQjCOZTIaVlRU+/fRTVlZWKBQKyLKMyWRCo9HgcrlEIMWRI0cYGBigp6cHo9HYdtqHRqMRFttXX32V0dFRoYl5vV6Gh4eRJIn+/v5tdo1UKsXa2hqFQoF4PE6xWGRjY4NUKsXCwgILCwu7ruY+il0X1nq9TiQSYWlpiV//+te88847ZLNZYrGYELzGSVB2xUZ/l2I8ehzhvBeNRkNvby8DAwOMjo4Kn1i7LcLPSz6fZ2tri5s3b/LRRx+xsbEhTg6TyYTJZGJsbIxAIMCXv/xl3nrrLYxGoxDUdtvUNBoNFosFWZY5fvw4R44cAe6uQ41GI4xmw8PD215XqVQoFovUajVyuRyVSoVbt26xvLyM1Wrlzp077S2ssixTrVaFlUy5NyqnpXJyXr16lWAwyMrKCslkkmKxeJ/LRWEndeLe+4Ner8dut2MwGIQbIhQKsbm5ue11Go0Gk8nEkSNHmJycpK+vb18Zl+7VMBR1T3FflctlFhcXWV1dJRwOU6lUcLvduFwu9Ho9fX19mM1m+vv76e7uZnx8XNxRFUFt17lSDJWSJFGtVsWVSTEM3Uvjc5SNPJvNsrW1RS6Xe+BneL1eRkZG6Ojo2PW5+kLCqviaCoUCm5ubbG1tEY1GWVpaIpFIcO3aNeLxOLFYjHw+T6FQECrYgy7v9XqdUqm07WS9F7vdzsmTJ/F6vZw8eZKOjg5+8pOf8Pbbb4vnaDQajEYjbrebP/iDP+ArX/kKBoMBrVbbtguwkUbLuLLpxeNxbt26RSQS4eLFiyQSCYLBINFoVJyihw4d4vXXX6ezs5Ph4WFsNhtWq1WcpEqwwH6YI61WKzYx5QApl8sP9anC3TVYq9VYWlri+vXrLC8vP9AuMjU1xZkzZ5icnGxtYW002kSjUYLBILFYjGAwSDKZZHZ2lnQ6LXb5RleAIjQGg2FHlVSJsFHiNBsnoquri0AggMvlorOzE6fTeV/8q2IVNJvNeDweLBZLW6p196IsJGVTU+5j1WqVzc1NEQSQTCZFYITRaKSjowOfz4ff72doaAiXy0VHRwcmkwmDwdB2hqTHoTFwJpFIUKlUKBQKj2XlLZVKxGIx4vE4uVzuPmFVAk2cTic9PT3Y7fbWFtZqtcqlS5e4fv06MzMz3Lx5k1KpJHT+dDpNpVKhVqtt+7IGgwG3243FYmFqagqHw3HfezscDp599lm8Xi8ul2ubMOp0OqxWK9VqldXVVWKxGMVicdvrjUYjw8PD9Pf3Y7PZmhZ8/bQpFossLS2RTCb56KOPWF9fZ2tri3Q6jcFgECfo0NAQFouFoaEhvF4vbrcbj8eDwWAQ86FELrX7BrYTjbaOCxcu8L/+1/+iUCiQSCR2dO0BQog1Gg21Wo1gMEgqlbpvbWm1WmG0PHLkCM8++yw2m23X7SBfWA0OhUIsLi5y9epVbt++vePzGgMdlBNPsUD6/X48Hs99r/F6vTz33HO4XC4cDodwSSgof4xIJCI2h8bP0+v1dHR04PF4thms2p1qtUokEiEYDHLx4kVu377NxsYG8Xicrq4uJiYm6O7uFsH9ExMTdHR0YLPZ9l2o5aNQ7vCLi4t88MEHVFTosAAAEH5JREFU4g6608n6oHzgnVBsIQ6HQwjtXmgmX1gNTqVS4k7aiFarxeVyYTQa6ezsFMLpdDrp6Ojg+PHjQoXYyedpMBjw+XzodLr74lRzuRy3bt1ic3OT9957j5WVFaanp4G7J3JPTw+jo6N85zvfYWBggO7u7i/yNVuKdDrN3/7t3xIOh7l69SrJZBJJkujs7GRycpKXX34Zn8/HqVOncDqd+Hw+zGbzvlRzH4VyR81kMuKEfBoW3Xq9TrFYJJlMcuvWLfx+P36/n/7+/taNDZZlWbhh7lUV9Ho9brcbh8PB+Pg4HR0ddHd34/f7GRgY4Pjx48KJ/6QqajKZ5JNPPmFlZYV3332XlZUV8ZjNZmNsbIzDhw/zyiuv4PF42ioC51Fks1l+8YtfsLS0JCzqnZ2deL1eBgcHOXXqFB0dHSKP1WQyHUhBVQIWKpWKsKs8STzwo967VCqh1WpZWlri/PnzvPjii/j9/taNDdbpdLz00ks4nU4R1qag1+vx+XyYTCb6+/vxeDw4nU4cDodQG570vqRYQEulEslkkmQyuS36Ce6erIODg/T392M0Gvfdncxut/PGG2+wvr7O6uoq6XRaRNDE43EuXryIw+FgY2MDm80mjGvKvCvROwfFz7wbKEYrgHA4LLTHqakpcQDtxvx+IWE1GAy88sorvPzyy5RKJZF2BHfVYCVCxmQyCaFRBKfxDvu4KP7cfD5POBxmdXV122cC9PT0cPLkSQYHBzGZTPvqVIW7sdP/6l/9K9LpNOfOnWN9fZ3p6WmuXr3K9PQ0c3Nzwm1lMBgYGhrC7Xbz4osv8tJLL4kUuf3inmkGShhnoVDg8uXLzM7OYjQaef7553E6nbjd7tYTVsWQo2QzGI3GbY8pd03lOV8UxWCQzWbJZDLCHA8It4xyZ1UilfYbWq1WaCaHDh3CbrdTrVYxm83bgiQa46dTqRQrKyv09PSIIBIlOX2/WMl3QlmXJpMJi8UiEs2fFoo6DHfDFbe2tpAkCafT+dQ+o5GnIqyyLO94L3raFeHy+TwrKyvcuHGDy5cviywJAJPJhNlsJhAIMDU1hc1m25d3NcUW4HK5+P/bO7entM4ujD+AorDlJHI+Gw9UG0tNbUksZpKZNhcdO5nppFdtc9OL9u/pn9BMpzeZyaRjNe0knUkPSTpmUok2Wg5GEFABRdiAChu/i3zvW4iYJkYRcP/ulJk98rrX3u+71rOepdFoUCqVMD4+XpEN39nZQSKRAMuy+OGHHzA7O4upqSl89913GBwcxOXLl2GxWPD2229DJpMd47c5Osi9KZPJYDQa4XA4aPfRYZ1dAVT0Uf/444/o6+uDXq+veHEdFq+9R6zVdoo8xVKpFBKJBDKZDBViE3EFafFiGKYhG6dfBnITAthTziIUi0W0tbWBZVmo1WowDEMbsQUCAVwuF4RCIYaGhmr5p9ccIqhRKBQ0h8GybNXaf7lQZ788B8dxyOfzVJRCRBelUgnpdBorKytQKBQvJbo4CA1xoCOLE4lEMDExgXA4TLPPpLRjs9nQ29uL7u5uiMXipjQDe1mEQiFkMhmkUik+/fRTXLp0CZOTk7h27RoYhsHc3BxSqRTOnz8PpVJ53H/ukVB+RHO73bBardjY2MD09DRYlkU8Hq/oulEqlTAYDLSft9qbcX5+Ht9++y1isRhisVhFuXJjYwNzc3MQi8X7ii5el7oPVvLk4jgOiUQCf//9N6LRKIrFIn0KtrS0QKPRwGg0QqvVVjgCnERIggkArFYrdnd3kUgk8MsvvyCfz2NpaYla4zQz5D7o6upCV1cXstksFAoF0uk0gsFgRfO52WxGT08PbaWstmuxWCz49ddf6b1YTjabxfLyMqxW66Fus8up22AtD9JwOEx9hXw+HzKZDIrFIkQiEXQ6HZRKJUZHR3Hx4sUjr3U1IkQ1plKp0NbWho2NjRO562htbYXRaERXVxe0Wm1FskkqlUKhUFSt+xM/5mw2i1wuB5Zl92x1y90Qj4q6DVbgXwXKgwcP8Ntvv8Hr9SIQCNCFam9vh9VqhclkwgcffAC3282XJJ6DrEV7ezsViBC3jJMGUcX9F8/fP8ViEVtbW0in00ilUkin00e21X0RdRusRNLFsiztx4zH4xXjDdra2qgzX7OWag4T/iF2sDUoFApYX1/H6uoq7ccmxnsEuVyOwcFBmEymI6vt122wFgoFRCIRrK2tYXp6Grdv36ZtdqTjX6lUwuPxwOVyNZX+l6e+WF9fx7179zA7O4twOFy1GaC3txcfffTRvsmpw6Aug5WkxLPZLDY3N2lPLIGoojo6OmhnzX5ljJNOuYvE1tZWxSwXnhdDHEpSqRSWl5eRTCapHrscgUAAiUQCrVZ7pH2tdResJKm0s7ODWCyGp0+f0pkjBIZh0N/fj56eHmrX0myywsOgvKeTdCaJxWJotVqoVCp+zV4Ax3EIhUKIRCK4c+cObt68iVQqVVHuAUDLhJ2dnTCbzVCr1Ud2HKu7/1a5vSMR65frf0lmU6/X017Ckz4l7UUQiebGxgbi8TjkcjksFgt14Wh0XqUP9VWuWSqVkEgkMD8/j0AgQJ39ny93kcYIImk8yt7puglW4iVEisuhUAi3bt2iySXgWeG6s7MTLpcLV65cgcViqeoycdIhNVSO4+D3+xEIBOD1epHP52G323H+/Hk4HA4wDHPcf+qBIN+vVCpR1/1yx33SQHIQdnZ2EI1GkUqlMDk5iZmZGfj9/n23vxqNhjpnGgwGOqnvKKirYOU4DvF4HBMTE4hGo5iamqpou5PJZOju7obT6cTY2Bj/Vt2HcqdDr9eLBw8e4J9//sHW1hbkcjneeecd6rbfiJDvVywWqVE8meJGuo0OGqyFQgELCwvw+/24e/cu7t+/Tx08q6HVauFwOGC324/cFL1ugpV000QiESwuLiISidDtr0QigVgshsvlwujoKN544w0wDHOiJYXVIC2EW1tbmJ+fRyKRwF9//YVQKITOzk58/PHHGBgYQFdXF2QyWcNug3d3d5HJZMCyLHw+H548eQKJREKdSLq7uyGVSqFUKumZcr/zOZGyktlJyWQSf/75J8LhMGKx2B4NMfAswalWqyGVSnHmzBmMjIygr6+vvj2YDgsyh2ZxcRF//PEHbt++jWw2SzOX5J8wNjaGL774gp4PmsGt8DAhvb7RaBTffPMN5ubmaPfN559/jqtXr6KzsxN6vZ5ajjYiHMchGo0iFArh+vXruHnzJiQSCeRyOXQ6HdxuN3Q6HS5evAiz2QypVLpvsJIBVvF4nIpuvv/+ezopvZp0UCwWo6+vDyaTCePj4zh79mxNGvqPNVjJdobjOKyvryMQCNC2N6IQEQgEUKlUMJlM1E+o3ISaB9RcPZvNIhqNYmlpiRbwlUoljEYjzGYzOjs7qbNho68dsWwhwhlyht3d3UU0GsX29jb8fj84joNarYZarabJoPLvTpRJq6ur8Pl8dAYTET6UQ+bnKBQK9Pf3Q6/X0+NELdb0WIOVJJQymQwmJiZw48YNrK2tVWg2W1tbMTIygtOnT+P06dM0edDoN9thQerRqVQKMzMzuHbtGuLxOBYWFiAQCPDJJ5/g3LlzOHXqFAwGAx2a3GyQ6gHLsrh16xbEYjF+//13qFQqOJ1ODA4Owm63w+Vy0TxHqVTCkydP8OjRIywsLGBycpKuZbUzqtlsxpUrV2AwGPD+++9Tm9xatWMee7Dm83lsbm5iZWUFwWBwzxONDE4i7UvN8FZ4HcqnvpMMOsuySCaTePr0KR4/fkzHPTAMA4vFArvdToUjzbJ2xGSblE04jqNJNTLRIZvN0iQaaV2z2+2QSCQAnt1/ZL5vOBymY0iByhIQEZEolUoqb9XpdDShVKuH37EOUy4Wi1haWoLP58Py8jJYlqVnBDINTC6Xw2Qy4dSpUyfO97YaxF0+m81iZmYG0WgUwWAQkUgE6+vr4DgONpsNly5dgslkgsfjafgz6vMIhULodDpIJBKcO3cOQqEQkUgEXq8X29vb9IGfz+dRKBQwNzdHG8Pv3btXcX6NxWJYWVlBKpXaI84ngUgmGQwPD+Ps2bPU/K+WgQoc45uViB9WV1cRCoUqLFqAyvEXxMaEL9OADoxOJBK4c+cO/H4/5ufn6UBkrVYLjUYDj8cDk8kEvV7fsPXU/RAKhejo6EBLSwucTicymQzEYjH8fj8A0PuInOXX1tboDNr79+9XvWY1P2HiH6ZSqWCz2WCxWGAwGMAwzKH5ir0KNQ1Wsn3L5XIIBoNIJpO4e/cuAoEAlpeXAYCm4HU6HT788EMYDAa899570Gq1TTVXtXwCH8uyeySV5LNkMolMJkN/v7m5icXFRSp7M5vNcDgcaGlpoabper0eDocDMpmsKX2oiI2PSCRCT08PVCoV3nrrLfT19WF1dRVTU1M0C/68++XLXJuMHfV4PLBarXA4HBgcHKwQPRzHub/mwUqE0Tdu3EA4HMZPP/2ESCRCz6lSqRQ2mw1vvvkmvvzyS+h0OmpU3SyBCvyrwikUCggGg/B6vfQzMoE7n89jZmYGPp+v4rOtrS0wDIPR0VHYbDacOXMG3d3dkMlk1AaTnE+bac0IAoGA7rKkUiksFgu2t7fx7rvvIhKJYGVlBY8fP6Zn2Fe9dltbG+RyOcbGxjA2NgaLxQKdTnfsic2aBitJtSeTSSojzGazKJVKNFlgs9ngdrvpzXcQM/BGgZzbE4kE/H4//blcLshxHFQqFRiGoUZwHR0dkEgkGBgYgEajgdlshkKh2FPWasY1ex7yHVtaWugMpaGhISiVSgQCAUSjUaTTaWxublLBSLUtb/k0uO7ubnodjUYDhmGOPVCBGgdrJpNBMBjEw4cP8fPPP2NtbY0++Yju98KFC/j6668hk8mgVCqbtjOEBGQul8P09DSuX79Oa4YCgYAG5vDwMAYGBmCxWKj+1Ol0orW1lSq4yLasPECP+8aqNWREqE6nw9WrV5HL5TA7O4tAIID5+Xk8fPiQWpFW857q6+vD5cuXYbVa4fF4IJfL9wyWPm5q/mbd3Nyks0PL243IYZ6MeiBdIfWwSEcFCbSOjg5otVrkcjmqhJHL5ZBKpdDpdDAajbBYLDCZTFCr1dQTuZnX5lUhDyqRSASZTIb29naYTCYAz4QPmUwG6XQa7e3tVYO1t7cXDoeDikckEknd7U5qGqzpdBqPHj3C4uLinjR5+Vj58t81K0KhEAzDQCKR4LPPPsP4+DjNkAOgW38yAY5oXImbYzOvzetAjAnEYjGcTid6enrgdrup32+hUKi6DSaJzZaWFprIrLc1rmmwkr7KbDa7R3MpFAorhvvW20IdNuVm3RqN5qWMvHj+G/J2JaKJZqKmwUrGPxaLxYqFFAqF6O/vh8vlwtDQEH2bNHvA8vC8CjUNVolEAofDgUQiUVFQFggEsFqtGB4ehs1mo8JoHh6ef6lpsEqlUpjNZohEInz11Ve02C8SiTAyMgKn0wmtVsu/UXl4qiD4j7Htrz/Tvfxi/xdFlCdSCEKhkCaY6qgr5HWeGoe6dg0Iv3YHp+ra1TRYGxD+hjs4/NodnAMFKw8PT51QN/tNHh6eF8MHKw9Pg8AHKw9Pg8AHKw9Pg8AHKw9Pg8AHKw9Pg/A/cJ43xos8u4wAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 288x288 with 9 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "dls = mnist.dataloaders(untar_data(URLs.MNIST_TINY))\n",
    "dls.show_batch(max_n=9, figsize=(4,4))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "jupytext": {
   "split_at_heading": true
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
